package com.justgame.project.generator.schema;

import com.justgame.project.generator.container.EntityContainer;
import com.justgame.project.generator.enums.JoinType;
import com.justgame.project.generator.utils.EntityUtils;
import com.justgame.project.generator.utils.NameUtils;
import lombok.Getter;
import lombok.NonNull;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

@Getter
@SuppressWarnings("all")
public class Join {
    private String alias;
    private final Entity targetEntity;
    private final Field targetEntityField;
    private final Entity sourceEntity;
    private final Field sourceEntityField;
    private final JoinType joinType;

    private Join(String alias,Entity targetEntity, Field targetEntityField, Entity sourceEntity, Field sourceEntityField, JoinType joinType) {
        this.alias = alias;
        this.targetEntity = targetEntity;
        this.targetEntityField = targetEntityField;
        this.sourceEntity = sourceEntity;
        this.sourceEntityField = sourceEntityField;
        this.joinType = joinType;
    }

    public static Join.JoinBuilder leftJoin(String alias, @NonNull String sourceColumn,@NonNull String joinTable,@NonNull String targetColumn) {
        return new Join.JoinBuilder(alias,sourceColumn,joinTable,targetColumn, JoinType.LEFT_JOIN);
    }

    public static Join.JoinBuilder leftJoin(@NonNull String sourceColumn,@NonNull String joinTable,@NonNull String targetColumn) {
        return leftJoin(null,sourceColumn,joinTable,targetColumn);
    }

    public static Join.JoinBuilder join(String alias, @NonNull String sourceColumn,@NonNull String joinTable,@NonNull String targetColumn) {
        return new Join.JoinBuilder(alias,sourceColumn,joinTable,targetColumn, JoinType.INNER_JOIN);
    }

    public static Join.JoinBuilder join(@NonNull String sourceColumn,@NonNull String joinTable,@NonNull String targetColumn) {
        return join(null,sourceColumn,joinTable,targetColumn);
    }

    public static Join.JoinBuilder rightJoin(String alias,@NonNull String sourceColumn,@NonNull String joinTable,@NonNull String targetColumn) {
        return new Join.JoinBuilder(alias,sourceColumn,joinTable,targetColumn, JoinType.RIGHT_JOIN);
    }

    public static Join.JoinBuilder rightJoin(@NonNull String sourceColumn,@NonNull String joinTable,@NonNull String targetColumn) {
        return rightJoin(null,sourceColumn,joinTable,targetColumn);
    }

    public static class JoinBuilder{
        private String alias;
        private String sourceColumn;
        private String joinTable;
        private String targetEntityFieldName;
        private JoinType joinType;

        public JoinBuilder(String alias,String sourceColumn, String joinTable, String targetEntityFieldName, JoinType joinType) {
            this.alias = alias;
            this.sourceColumn = sourceColumn;
            this.joinTable = joinTable;
            this.targetEntityFieldName = targetEntityFieldName;
            this.joinType = joinType;
        }

        public Join build(@NonNull Entity sourceEntity,@NonNull EntityContainer container){
            Entity targetEntity = container.findEntity((entity)->entity.getName().equals(joinTable)).orElse(null);
            Assert.notNull(targetEntity,"实体类 "+ sourceEntity.getName() + " 创建关联表时异常：不存在 "+joinTable+" 目标实体");
            Field targetField = EntityUtils.findField(targetEntity,targetEntityFieldName).orElse(null);
            Assert.notNull(targetField,"实体类 "+ sourceEntity.getName() + " 创建关联表时异常："+joinTable+" 中不存在 "+targetEntityFieldName+" 目标关联字段");
            Field sourceField = EntityUtils.findField(sourceEntity,sourceColumn).orElse(null);
            Assert.notNull(sourceField,"实体类 "+ sourceEntity.getName() + " 创建关联表时异常："+sourceEntity.getName()+" 中不存在 "+sourceColumn+" 目标关联字段");
            alias = StringUtils.hasLength(alias) ? alias : NameUtils.firstWorldLower(joinTable);
            return new Join(alias,targetEntity,targetField,sourceEntity,sourceField,joinType);
        }
    }
}
